package com.mz.ieann.doplayer.audio.widget

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView
import com.mz.ieann.doplayer.audio.AudioHelper

/**
 * <p>------------------------------------------------------
 * <p>Copyright (C) 2020 wasu company, All rights reserved.
 * <p>------------------------------------------------------
 * <p>
 * <p>
 *
 * @author Created by zhangmz
 * @date on 2023/5/11
 */
class VisualizerView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0
): SurfaceView(context, attrs, defStyle), SurfaceHolder.Callback {

    /**
     * 指定的SurfaceHolder，用来获取画板
     */
    private var surfaceHolder: SurfaceHolder? = null

    /**
     * SurfaceHolder 的 canvas
     */
    private var surfaceCanvas: Canvas? = null

    private var points: FloatArray? = null
    private val paint = Paint()
    private val rect = Rect()

    /**
     * h绘制频谱的样式
     */
    private var type: Int = 0

    init {
        holder.addCallback(this)
        // 设置可执行onDraw
        setWillNotDraw(false)
        // 设置背景透明
        holder.setFormat(PixelFormat.TRANSPARENT)

        // 设置可获焦
        isClickable = true
        isFocusable = true
        isFocusableInTouchMode = true
        // 设置常亮
        keepScreenOn = true

        // 设置画笔的属性
        paint.strokeWidth = 1f
        paint.isAntiAlias = true
        paint.color = Color.RED
        paint.style = Paint.Style.FILL
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        Log.v(AudioHelper.TAG, "surfaceCreated")
        setZOrderOnTop(true)
        create(holder)
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        Log.v(AudioHelper.TAG, "surfaceChanged")
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        Log.v(AudioHelper.TAG, "surfaceDestroyed")
        destroy()
    }

    private fun create(holder: SurfaceHolder){
        surfaceHolder = holder
        surfaceCanvas = surfaceHolder?.lockCanvas()
        // 使用rect对象记录该组件的宽度和高度
        Log.v(AudioHelper.TAG, "create, width:$width; height:$height; measuredWidth:$measuredWidth; measuredHeight:$measuredHeight; surfaceCanvas:$surfaceCanvas")
        rect.set(0, 0, measuredWidth, measuredHeight)
    }

    private fun destroy(){
        if (surfaceCanvas != null){
            surfaceHolder?.unlockCanvasAndPost(surfaceCanvas)
        }
        surfaceCanvas = null
        surfaceHolder = null
    }

    fun drawStop(){
        if (surfaceCanvas != null){
            surfaceHolder?.unlockCanvasAndPost(surfaceCanvas)
        }
    }

    fun setDrawType(type: Int){
        this.type = type
    }

    fun updateVisualizer(bytes: ByteArray?){
        try {
            surfaceCanvas?.let {
                when(type){
                    0 -> drawWaveform(it, bytes)
                    1 -> drawHistogram(it, bytes)
                    2 -> drawGraph(it, bytes)
                }
            }?: Log.v(AudioHelper.TAG, "surfaceCanvas can not be null")
        }catch (e: Exception){
            Log.e(AudioHelper.TAG, "draw spectrum error:$e")
        }
    }

    /**
     * 绘制块状的波形图
     */
    private fun drawWaveform(canvas: Canvas, bytes: ByteArray?){
        bytes?.let {
            for (i in 0 until it.size - 1) {
                val left = (width * i / (it.size - 1)).toFloat()
                // 依据波形值计算该矩形的高度
                val top =
                    (rect.height() - (it[i + 1] + 128).toByte() * rect.height() / 128).toFloat()
                val right = left + 1
                val bottom = rect.height().toFloat()
                canvas.drawRect(left, top, right, bottom, paint)
            }
        }?: Log.e(AudioHelper.TAG, "drawWaveform, bytes can not be null")


//        bytes?.let { data ->
//            Log.v(AudioHelper.TAG, "drawWaveform, data size:${data.size}")
//            data.forEachIndexed { i, byte ->
//                val left: Float = (width * i / (data.size - 1)).toFloat()
//                // 依据波形值计算该矩形的高度
//                val top = (rect.height() - (data[i + 1] + 128).toByte() * rect.height() / 128).toFloat()
//                val right = left + 1
//                val bottom = rect.height().toFloat()
//                Log.v(AudioHelper.TAG, "drawWaveform, left:$left; top:$top; right:$right; bottom:$bottom")
//                canvas.drawRect(left, top, right, bottom, paint)
//            }
//        }?: Log.e(AudioHelper.TAG, "drawWaveform, bytes can not be null")
    }

    /**
     * 绘制柱状的波形图（每隔18个抽样点绘制一个矩形）
     */
    private fun drawHistogram(canvas: Canvas, bytes: ByteArray?){
        bytes?.let { data ->
            {
                var i = 0
                while (i < data.size - 1) {
                    i += 18
                    val left = (rect.width() * i / (data.size - 1)).toFloat()
                    // 依据波形值计算该矩形的高度
                    val top = (rect.height() - (data[i + 1] + 128).toByte() * rect.height() / 128).toFloat()
                    val right = left + 6
                    val bottom = rect.height().toFloat()
                    Log.v(AudioHelper.TAG, "drawHistogram, left:$left; top:$top; right:$right; bottom:$bottom")
                    canvas.drawRect(left, top, right, bottom, paint)
                }
            }
        }?: Log.e(AudioHelper.TAG, "drawHistogram, bytes can not be null")
    }

    /**
     * 绘制曲线波形图
     */
    private fun drawGraph(canvas: Canvas, bytes: ByteArray?){
        bytes?.let { data ->
            // 假设point数组还未初始化
            if (points == null || (points?.size ?: 0) < data.size * 4) {
                points = FloatArray(data.size * 4)
            }
            for (i in 0 until data.size - 1) {
                // 计算第i个点的x坐标
                points!![i * 4] = (rect.width() * i / (data.size - 1)).toFloat()
                // 依据bytes[i]的值（波形点的值）计算第i个点的y坐标
                points!![i * 4 + 1] = (rect.height() / 2 + (data[i] + 128).toByte() * 128 / (rect.height() / 2)).toFloat()
                // 计算第i+1个点的x坐标
                points!![i * 4 + 2] = (rect.width() * (i + 1) / (data.size - 1)).toFloat()
                // 依据bytes[i+1]的值（波形点的值）计算第i+1个点的y坐标
                points!![i * 4 + 3] = (rect.height() / 2 + (data[i + 1] + 128).toByte() * 128 / (rect.height() / 2)).toFloat()
            }
            Log.v(AudioHelper.TAG, "drawGraph, points:$points")
            // 绘制波形曲线
            canvas.drawLines(points!!, paint)
        }?: Log.e(AudioHelper.TAG, "drawGraph, bytes can not be null")
    }

}